"""
TypeScript MCP server implementation.

Provides TypeScript-specific code analysis tools for function call tree generation
and code understanding through TypeScript AST parsing and analysis.
"""

import json
import subprocess
from typing import Dict, List, Any, Optional, Union
from pathlib import Path

from ...core.base_mcp import BaseMCP
from ...core.error_handler import CodeMCPError, AnalysisError, log_info
from ...parsers.typescript.ts_compiler import TypeScriptCompiler
from ...parsers.typescript.symbol_walker import SymbolWalker
from ...parsers.typescript.module_resolver import ModuleResolver as TSModuleResolver
from .analyzer import TypeScriptCallGraphAnalyzer, TypeScriptDependencyAnalyzer
from .modules import TypeScriptModuleAnalyzer, ModuleResolver, ModuleDependencyGraph
from .types import TypeScriptTypeAnalyzer, TypeInferenceEngine
from .dynamic_calls import TypeScriptDynamicCallDetector, CallPatternAnalyzer
from .async_analysis import TypeScriptAsyncAnalyzer, AsyncPatternValidator
from .resolver import TypeScriptDependencyResolver, DependencyAnalyzer
from .workspace import WorkspaceDetector, WorkspaceDependencyResolver, WorkspaceAnalyzer


class TypeScriptMCP(BaseMCP):
    """TypeScript-specific MCP server for code analysis."""
    
    def __init__(self, config=None):
        """Initialize TypeScript MCP server."""
        super().__init__(name="typescript_mcp", language="typescript", config=config)
        
        # Initialize TypeScript compiler and parsers
        self.compiler = TypeScriptCompiler()
        self.symbol_walker = SymbolWalker()
        self.ts_module_resolver = TSModuleResolver()
        
        # Initialize analyzers
        self.call_analyzer = TypeScriptCallGraphAnalyzer()
        self.dependency_analyzer = TypeScriptDependencyAnalyzer()
        self.module_analyzer = TypeScriptModuleAnalyzer()
        self.type_analyzer = TypeScriptTypeAnalyzer()
        self.dynamic_detector = TypeScriptDynamicCallDetector()
        self.async_analyzer = TypeScriptAsyncAnalyzer()
        
        # Initialize resolvers and validators
        self.dependency_resolver = TypeScriptDependencyResolver()
        self.module_resolver = ModuleResolver()
        self.dependency_graph = ModuleDependencyGraph()
        self.type_inference = TypeInferenceEngine()
        self.pattern_analyzer = CallPatternAnalyzer()
        self.async_validator = AsyncPatternValidator()
        self.dep_analyzer = DependencyAnalyzer()
        
        # Initialize workspace components
        self.workspace_detector = WorkspaceDetector()
        self.workspace_resolver = None  # Will be initialized when workspace is detected
        self.workspace_analyzer = None  # Will be initialized when workspace is detected
        self.workspace_info = None
        
        # Register TypeScript-specific tools
        self._register_tools()
    
    async def _register_default_tools(self):
        """Register default tools for this MCP server."""
        # This is now handled by _register_tools()
        pass
    
    async def _initialize_language_components(self):
        """Initialize language-specific components."""
        # Components are already initialized in __init__
        pass
    
    def _is_supported_file(self, file_path: Path) -> bool:
        """Check if file is supported by this MCP server."""
        return file_path.suffix in self._get_supported_extensions()
    
    def _get_supported_extensions(self) -> List[str]:
        """Get list of supported file extensions."""
        return ['.ts', '.tsx', '.js', '.jsx', '.d.ts']
    
    async def parse_file(self, file_path: str) -> Any:
        """Parse a TypeScript file and return analysis structure."""
        file_path = Path(file_path)
        if not file_path.exists():
            raise AnalysisError(f"File not found: {file_path}")
        
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                source_code = f.read()
            
            # Comprehensive analysis of the TypeScript file
            analysis = {
                'file_path': str(file_path),
                'modules': self.module_analyzer.analyze_modules(source_code, str(file_path)),
                'types': self.type_analyzer.analyze_types(source_code, str(file_path)),
                'dynamic_calls': self.dynamic_detector.detect_dynamic_calls(source_code, str(file_path)),
                'async_patterns': self.async_analyzer.analyze_async_patterns(source_code, str(file_path)),
                'ast': await self._parse_with_typescript(str(file_path))
            }
            
            return analysis
            
        except Exception as e:
            raise AnalysisError(f"Failed to parse TypeScript file {file_path}: {str(e)}")
    
    async def build_call_tree(self, entry_point: str, max_depth: int = None) -> Any:
        """Build a call tree from an entry point."""
        from ...core.base_mcp import CallTree, CallTreeNode
        
        try:
            # Parse the entry point file
            analysis = await self.parse_file(entry_point)
            
            # Build call graph from functions/methods
            functions = self._extract_functions_from_analysis(analysis)
            
            if not functions:
                return CallTree(root=None, metadata={'error': 'No functions found in entry point'})
            
            # Use the first function as root (or find main/default export)
            root_function = self._find_entry_function(functions, analysis)
            
            # Build call graph
            call_graph = self.call_analyzer.analyze_function_calls(root_function, analysis, max_depth or 10)
            
            # Convert to CallTree format
            root_node = self._convert_to_call_tree_node(call_graph['graph'])
            
            metadata = {
                'entry_point': entry_point,
                'root_function': call_graph['root_function'],
                'total_calls': call_graph['total_calls'],
                'max_depth': call_graph['max_depth'],
                'unique_functions': call_graph['unique_functions'],
                'async_patterns': call_graph.get('async_patterns', {}),
                'statistics': call_graph.get('statistics', {})
            }
            
            return CallTree(root=root_node, metadata=metadata)
            
        except Exception as e:
            raise AnalysisError(f"Failed to build call tree for {entry_point}: {str(e)}")
    
    async def analyze_dependencies(self, file_path: str) -> Dict[str, Any]:
        """Analyze dependencies for a TypeScript file."""
        try:
            analysis = await self.parse_file(file_path)
            imports = analysis['modules'].get('imports', [])
            
            # Resolve dependencies
            resolution = self.dependency_resolver.resolve_dependencies(file_path, imports)
            
            # Analyze dependency patterns
            if imports:
                dependency_graph = self.dependency_resolver.get_dependency_graph([file_path])
                patterns = self.dep_analyzer.analyze_dependency_patterns(dependency_graph)
                resolution['patterns'] = patterns
            
            return resolution
            
        except Exception as e:
            raise AnalysisError(f"Failed to analyze dependencies for {file_path}: {str(e)}")
    
    async def detect_workspace(self, project_path: str = None) -> Dict[str, Any]:
        """Detect and analyze npm/yarn workspace configuration."""
        try:
            if project_path:
                self.workspace_detector = WorkspaceDetector(project_path)
            
            workspace_info = self.workspace_detector.detect_workspace()
            
            if workspace_info['is_workspace']:
                self.workspace_info = workspace_info
                self.workspace_resolver = WorkspaceDependencyResolver(workspace_info)
                self.workspace_analyzer = WorkspaceAnalyzer(workspace_info)
                
                log_info(f"Detected {workspace_info['workspace_type']} workspace with {len(workspace_info['packages'])} packages")
            
            return workspace_info
            
        except Exception as e:
            raise AnalysisError(f"Failed to detect workspace: {str(e)}")
    
    async def analyze_workspace(self, project_path: str = None) -> Dict[str, Any]:
        """Perform comprehensive workspace analysis."""
        try:
            # First detect workspace if not already done
            if not self.workspace_info:
                await self.detect_workspace(project_path)
            
            if not self.workspace_info or not self.workspace_info['is_workspace']:
                return {
                    'error': 'No workspace detected',
                    'is_workspace': False
                }
            
            # Perform detailed analysis
            analysis = self.workspace_analyzer.analyze_workspace()
            
            # Add workspace detection info
            analysis['workspace_detection'] = self.workspace_info
            
            return analysis
            
        except Exception as e:
            raise AnalysisError(f"Failed to analyze workspace: {str(e)}")
    
    async def analyze_cross_package_dependencies(self, project_path: str = None) -> Dict[str, Any]:
        """Analyze dependencies between workspace packages."""
        try:
            if not self.workspace_info:
                await self.detect_workspace(project_path)
            
            if not self.workspace_info or not self.workspace_info['is_workspace']:
                return {
                    'error': 'No workspace detected',
                    'cross_package_dependencies': []
                }
            
            dependency_graph = self.workspace_resolver.get_workspace_dependency_graph()
            
            # Enhance with cross-package call analysis
            cross_package_calls = await self._analyze_cross_package_calls()
            
            return {
                'workspace_dependency_graph': dependency_graph,
                'cross_package_calls': cross_package_calls,
                'analysis_summary': {
                    'total_packages': len(dependency_graph['packages']),
                    'internal_dependencies': sum(len(deps) for deps in dependency_graph['dependencies'].values()),
                    'circular_dependencies': len(dependency_graph['cycles']),
                    'orphaned_packages': len(dependency_graph['orphaned_packages']),
                    'cross_package_function_calls': len(cross_package_calls.get('calls', []))
                }
            }
            
        except Exception as e:
            raise AnalysisError(f"Failed to analyze cross-package dependencies: {str(e)}")
    
    async def _analyze_cross_package_calls(self) -> Dict[str, Any]:
        """Analyze function calls that cross package boundaries."""
        if not self.workspace_info:
            return {'calls': [], 'summary': {}}
        
        cross_package_calls = []
        packages = self.workspace_info.get('packages', [])
        
        # For each package, analyze its source files for imports and calls
        for package in packages[:5]:  # Limit to first 5 packages for performance
            try:
                package_path = Path(package['path'])
                source_files = package.get('source_files', [])
                
                for source_file in source_files[:10]:  # Limit files per package
                    file_path = package_path / source_file
                    if file_path.exists() and file_path.suffix in ['.ts', '.tsx', '.js', '.jsx']:
                        file_analysis = await self.parse_file(str(file_path))
                        
                        # Check imports for workspace references
                        imports = file_analysis.get('modules', {}).get('imports', [])
                        for import_info in imports:
                            resolution = self.workspace_resolver.resolve_workspace_import(
                                import_info.get('module', ''), 
                                package['name']
                            )
                            
                            if resolution['is_workspace_internal']:
                                cross_package_calls.append({
                                    'from_package': package['name'],
                                    'from_file': str(file_path.relative_to(package_path)),
                                    'to_package': resolution.get('target_package'),
                                    'import_path': import_info.get('module'),
                                    'resolved_path': resolution.get('resolved_path'),
                                    'import_type': import_info.get('type', 'unknown'),
                                    'line': import_info.get('line', 0)
                                })
                                
            except Exception as e:
                log_debug(f"Error analyzing package {package['name']}: {e}")
                continue
        
        return {
            'calls': cross_package_calls,
            'summary': {
                'total_cross_package_calls': len(cross_package_calls),
                'packages_analyzed': min(5, len(packages)),
                'unique_target_packages': len(set(call['to_package'] for call in cross_package_calls if call['to_package']))
            }
        }
    
    def _register_tools(self):
        """Register TypeScript-specific MCP tools."""
        # Initialize tools list if not exists
        if not hasattr(self, 'tools'):
            self.tools = []
        
        tools = [
            {
                'name': 'analyze_typescript',
                'description': 'Analyze TypeScript code structure and patterns',
                'inputSchema': {
                    'type': 'object',
                    'properties': {
                        'file_path': {
                            'type': 'string',
                            'description': 'Path to the TypeScript file to analyze'
                        },
                        'include_types': {
                            'type': 'boolean',
                            'description': 'Include type analysis',
                            'default': True
                        },
                        'include_async': {
                            'type': 'boolean', 
                            'description': 'Include async pattern analysis',
                            'default': True
                        }
                    },
                    'required': ['file_path']
                }
            },
            {
                'name': 'build_typescript_call_tree',
                'description': 'Build function call tree for TypeScript code',
                'inputSchema': {
                    'type': 'object',
                    'properties': {
                        'entry_point': {
                            'type': 'string',
                            'description': 'Entry point file path'
                        },
                        'max_depth': {
                            'type': 'integer',
                            'description': 'Maximum depth for call tree',
                            'default': 10
                        }
                    },
                    'required': ['entry_point']
                }
            },
            {
                'name': 'analyze_typescript_dependencies',
                'description': 'Analyze TypeScript module dependencies',
                'inputSchema': {
                    'type': 'object',
                    'properties': {
                        'file_path': {
                            'type': 'string',
                            'description': 'Path to the TypeScript file'
                        }
                    },
                    'required': ['file_path']
                }
            },
            {
                'name': 'detect_dynamic_calls',
                'description': 'Detect dynamic function calls and eval usage in TypeScript',
                'inputSchema': {
                    'type': 'object',
                    'properties': {
                        'file_path': {
                            'type': 'string',
                            'description': 'Path to the TypeScript file'
                        }
                    },
                    'required': ['file_path']
                }
            },
            {
                'name': 'analyze_async_patterns',
                'description': 'Analyze async/await and Promise patterns in TypeScript',
                'inputSchema': {
                    'type': 'object',
                    'properties': {
                        'file_path': {
                            'type': 'string',
                            'description': 'Path to the TypeScript file'
                        },
                        'validate_patterns': {
                            'type': 'boolean',
                            'description': 'Validate async patterns for best practices',
                            'default': True
                        }
                    },
                    'required': ['file_path']
                }
            },
            {
                'name': 'detect_typescript_workspace',
                'description': 'Detect npm/yarn workspace configuration in TypeScript projects',
                'inputSchema': {
                    'type': 'object',
                    'properties': {
                        'project_path': {
                            'type': 'string',
                            'description': 'Path to the project root directory',
                            'default': '.'
                        }
                    }
                }
            },
            {
                'name': 'analyze_typescript_workspace', 
                'description': 'Perform comprehensive analysis of TypeScript workspace structure and health',
                'inputSchema': {
                    'type': 'object',
                    'properties': {
                        'project_path': {
                            'type': 'string',
                            'description': 'Path to the project root directory',
                            'default': '.'
                        }
                    }
                }
            },
            {
                'name': 'analyze_cross_package_dependencies',
                'description': 'Analyze dependencies and function calls between workspace packages',
                'inputSchema': {
                    'type': 'object',
                    'properties': {
                        'project_path': {
                            'type': 'string',
                            'description': 'Path to the project root directory',
                            'default': '.'
                        }
                    }
                }
            }
        ]
        
        for tool in tools:
            self.tools.append(tool)
    
    async def _parse_with_typescript(self, file_path: str) -> Dict[str, Any]:
        """Parse TypeScript file using TypeScript compiler API."""
        try:
            # Use the TypeScript compiler to parse the file
            ast_data = await self.compiler.parse_file(file_path)
            
            # Walk the symbol tree to extract function information
            symbols = await self.symbol_walker.walk_symbols(ast_data)
            
            return {
                'ast': ast_data,
                'symbols': symbols,
                'functions': self._extract_functions_from_symbols(symbols),
                'classes': self._extract_classes_from_symbols(symbols),
                'interfaces': self._extract_interfaces_from_symbols(symbols)
            }
            
        except Exception as e:
            log_info(f"TypeScript compiler parsing failed, falling back to regex analysis: {e}")
            return self._fallback_parse(file_path)
    
    def _fallback_parse(self, file_path: str) -> Dict[str, Any]:
        """Fallback parsing using regex patterns."""
        with open(file_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        return {
            'functions': self._extract_functions_regex(content),
            'classes': self._extract_classes_regex(content),
            'interfaces': self._extract_interfaces_regex(content),
            'ast': None,
            'symbols': None
        }
    
    def _extract_functions_from_analysis(self, analysis: Dict[str, Any]) -> List[Dict[str, Any]]:
        """Extract function information from comprehensive analysis."""
        functions = []
        
        # From AST analysis
        if analysis.get('ast', {}).get('functions'):
            functions.extend(analysis['ast']['functions'])
        
        # From async analysis
        async_functions = analysis.get('async_patterns', {}).get('async_functions', [])
        for async_func in async_functions:
            if not any(f['name'] == async_func['name'] for f in functions):
                functions.append(async_func)
        
        return functions
    
    def _find_entry_function(self, functions: List[Dict[str, Any]], analysis: Dict[str, Any]) -> Dict[str, Any]:
        """Find the entry function (main, default export, etc.)."""
        # Look for common entry patterns
        entry_names = ['main', 'index', 'start', 'run', 'execute']
        
        # First try to find by name
        for func in functions:
            if func['name'].lower() in entry_names:
                return func
        
        # Look for default export
        exports = analysis.get('modules', {}).get('exports', [])
        default_export = next((exp for exp in exports if exp.get('type') == 'default'), None)
        
        if default_export:
            export_name = default_export.get('value', '').strip()
            for func in functions:
                if func['name'] == export_name:
                    return func
        
        # Return first function if none found
        return functions[0] if functions else {'name': 'unknown', 'calls': []}
    
    def _convert_to_call_tree_node(self, graph: Dict[str, Any]) -> Any:
        """Convert call graph to CallTreeNode format."""
        from ...core.base_mcp import CallTreeNode
        
        def convert_node(node_data: Dict[str, Any]) -> CallTreeNode:
            children = []
            for call in node_data.get('calls', []):
                children.append(convert_node(call))
            
            node = CallTreeNode(
                name=node_data['name'],
                file_path='',
                line_number=node_data.get('line', 0),
                language='typescript',
                node_type=node_data.get('type', 'function')
            )
            
            # Add children
            node.callee_nodes = children
            
            # Store metadata
            node.call_frequency = 1
            node.call_context = {
                'async': node_data.get('async', False),
                'external': node_data.get('external', False),
                'call_type': node_data.get('type', 'function')
            }
            
            return node
        
        return convert_node(graph)
    
    def _extract_functions_from_symbols(self, symbols: Dict[str, Any]) -> List[Dict[str, Any]]:
        """Extract function information from TypeScript symbols."""
        functions = []
        
        for symbol in symbols.get('functions', []):
            functions.append({
                'name': symbol['name'],
                'line': symbol.get('line', 0),
                'type': 'function',
                'async': symbol.get('async', False),
                'parameters': symbol.get('parameters', []),
                'return_type': symbol.get('returnType', 'any'),
                'calls': symbol.get('calls', [])
            })
        
        return functions
    
    def _extract_classes_from_symbols(self, symbols: Dict[str, Any]) -> List[Dict[str, Any]]:
        """Extract class information from TypeScript symbols."""
        classes = []
        
        for symbol in symbols.get('classes', []):
            classes.append({
                'name': symbol['name'],
                'line': symbol.get('line', 0),
                'methods': symbol.get('methods', []),
                'properties': symbol.get('properties', []),
                'extends': symbol.get('extends'),
                'implements': symbol.get('implements', [])
            })
        
        return classes
    
    def _extract_interfaces_from_symbols(self, symbols: Dict[str, Any]) -> List[Dict[str, Any]]:
        """Extract interface information from TypeScript symbols."""
        interfaces = []
        
        for symbol in symbols.get('interfaces', []):
            interfaces.append({
                'name': symbol['name'],
                'line': symbol.get('line', 0),
                'properties': symbol.get('properties', []),
                'methods': symbol.get('methods', []),
                'extends': symbol.get('extends', [])
            })
        
        return interfaces
    
    def _extract_functions_regex(self, content: str) -> List[Dict[str, Any]]:
        """Extract functions using regex patterns as fallback."""
        import re
        
        functions = []
        
        # Function patterns
        patterns = [
            r'(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*\([^)]*\)',
            r'(?:export\s+)?const\s+(\w+)\s*=\s*(?:async\s*)?\([^)]*\)\s*=>\s*\{',
            r'(\w+)\s*:\s*(?:async\s*)?\([^)]*\)\s*=>\s*\{'
        ]
        
        lines = content.split('\n')
        for line_num, line in enumerate(lines, 1):
            for pattern in patterns:
                match = re.search(pattern, line)
                if match:
                    functions.append({
                        'name': match.group(1),
                        'line': line_num,
                        'type': 'function',
                        'async': 'async' in line,
                        'calls': []
                    })
        
        return functions
    
    def _extract_classes_regex(self, content: str) -> List[Dict[str, Any]]:
        """Extract classes using regex patterns as fallback."""
        import re
        
        classes = []
        
        pattern = r'(?:export\s+)?(?:abstract\s+)?class\s+(\w+)(?:\s+extends\s+(\w+))?'
        lines = content.split('\n')
        
        for line_num, line in enumerate(lines, 1):
            match = re.search(pattern, line)
            if match:
                classes.append({
                    'name': match.group(1),
                    'line': line_num,
                    'extends': match.group(2),
                    'methods': [],
                    'properties': []
                })
        
        return classes
    
    def _extract_interfaces_regex(self, content: str) -> List[Dict[str, Any]]:
        """Extract interfaces using regex patterns as fallback."""
        import re
        
        interfaces = []
        
        pattern = r'(?:export\s+)?interface\s+(\w+)(?:\s+extends\s+([^{]+))?'
        lines = content.split('\n')
        
        for line_num, line in enumerate(lines, 1):
            match = re.search(pattern, line)
            if match:
                extends = []
                if match.group(2):
                    extends = [ext.strip() for ext in match.group(2).split(',')]
                
                interfaces.append({
                    'name': match.group(1),
                    'line': line_num,
                    'extends': extends,
                    'properties': [],
                    'methods': []
                })
        
        return interfaces
    
    async def _extract_function_info(self, ast_data: Any, function_name: str) -> Optional[Dict[str, Any]]:
        """Extract function information from AST data."""
        try:
            functions = []
            
            # Extract from different sources
            if isinstance(ast_data, dict):
                if 'functions' in ast_data:
                    functions.extend(ast_data['functions'])
                if 'ast' in ast_data and ast_data['ast'] and 'functions' in ast_data['ast']:
                    functions.extend(ast_data['ast']['functions'])
            
            # Find the specific function
            for func in functions:
                if func.get('name') == function_name:
                    return func
            
            return None
            
        except Exception as e:
            log_info(f"Error extracting function info for {function_name}: {e}")
            return None
    
    async def _extract_dependencies(self, ast_data: Any) -> List[Dict[str, Any]]:
        """Extract dependencies from AST data."""
        try:
            dependencies = []
            
            if isinstance(ast_data, dict):
                # Extract from modules section
                modules = ast_data.get('modules', {})
                imports = modules.get('imports', [])
                
                for imp in imports:
                    dependencies.append({
                        'type': 'import',
                        'module': imp.get('module', ''),
                        'import_type': imp.get('type', 'unknown'),
                        'items': imp.get('items', []),
                        'line': imp.get('line', 0)
                    })
            
            return dependencies
            
        except Exception as e:
            log_info(f"Error extracting dependencies: {e}")
            return []
    
    # Tool handler methods
    async def handle_analyze_typescript(self, file_path: str, include_types: bool = True, 
                                       include_async: bool = True) -> Dict[str, Any]:
        """Handle analyze_typescript tool call."""
        analysis = await self.parse_file(file_path)
        
        result = {
            'file_path': file_path,
            'modules': analysis['modules'],
            'functions': self._extract_functions_from_analysis(analysis)
        }
        
        if include_types:
            result['types'] = analysis['types']
        
        if include_async:
            result['async_patterns'] = analysis['async_patterns']
            
            # Validate async patterns
            validation = self.async_validator.validate_async_patterns(analysis['async_patterns'])
            result['async_validation'] = validation
        
        return result
    
    async def handle_build_typescript_call_tree(self, entry_point: str, max_depth: int = 10) -> Dict[str, Any]:
        """Handle build_typescript_call_tree tool call."""
        call_tree = await self.build_call_tree(entry_point, max_depth)
        return call_tree.to_dict()
    
    async def handle_analyze_typescript_dependencies(self, file_path: str) -> Dict[str, Any]:
        """Handle analyze_typescript_dependencies tool call."""
        return await self.analyze_dependencies(file_path)
    
    async def handle_detect_dynamic_calls(self, file_path: str) -> Dict[str, Any]:
        """Handle detect_dynamic_calls tool call."""
        with open(file_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        dynamic_calls = self.dynamic_detector.detect_dynamic_calls(content, file_path)
        patterns = self.pattern_analyzer.analyze_call_patterns(dynamic_calls)
        
        return {
            'dynamic_calls': dynamic_calls,
            'patterns': patterns
        }
    
    async def handle_analyze_async_patterns(self, file_path: str, validate_patterns: bool = True) -> Dict[str, Any]:
        """Handle analyze_async_patterns tool call."""
        with open(file_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        async_analysis = self.async_analyzer.analyze_async_patterns(content, file_path)
        
        result = {'async_analysis': async_analysis}
        
        if validate_patterns:
            validation = self.async_validator.validate_async_patterns(async_analysis)
            result['validation'] = validation
        
        return result
    
    async def handle_detect_typescript_workspace(self, project_path: str = '.') -> Dict[str, Any]:
        """Handle detect_typescript_workspace tool call."""
        return await self.detect_workspace(project_path)
    
    async def handle_analyze_typescript_workspace(self, project_path: str = '.') -> Dict[str, Any]:
        """Handle analyze_typescript_workspace tool call."""
        return await self.analyze_workspace(project_path)
    
    async def handle_analyze_cross_package_dependencies(self, project_path: str = '.') -> Dict[str, Any]:
        """Handle analyze_cross_package_dependencies tool call."""
        return await self.analyze_cross_package_dependencies(project_path)